using System;
using System.Reflection;
using System.Collections.Generic;


namespace Framework.Event
{
    public sealed class EventManager : FrameworkModule
    {
        private EventDispatcher m_Event = new EventDispatcher();

        private Dictionary<string, List<IEvent>> m_Type2Event = new Dictionary<string, List<IEvent>>();

        public override void Init()
        {
            foreach (Type type in FrameworkEntry.GetTypes(typeof(EventAttribute)))
            {
                object[] attrs = type.GetCustomAttributes(typeof(EventAttribute), false);
                foreach (object attr in attrs)
                {
                    EventAttribute eventAttr = (EventAttribute)attr;
                    object obj = Activator.CreateInstance(type);
                    IEvent temp = obj as IEvent;
                    if (temp == null)
                    {
                        Log.Error($"{obj.GetType().Name} 没有继承IEvent");
                        continue;
                    }
                    this.RegisterEvent(eventAttr.EventType, temp);
                }
            }
        }

        public void RegisterEvent(string type, IEvent e)
        {
            if (!this.m_Type2Event.ContainsKey(type))
            {
                this.m_Type2Event.Add(type, new List<IEvent>());
            }
            this.m_Type2Event[type].Add(e);
        }

        public new void AddListener(string type, FrameworkAction func)
        {
            this.m_Event.AddListener(type, func);
        }

        public new void AddListener<A>(string type, FrameworkAction<A> func)
        {
            this.m_Event.AddListener<A>(type, func);
        }

        public new void AddListener<A, B>(string type, FrameworkAction<A, B> func)
        {
            this.m_Event.AddListener<A, B>(type, func);
        }

        public new void AddListener<A, B, C>(string type, FrameworkAction<A, B, C> func)
        {
            this.m_Event.AddListener<A, B, C>(type, func);
        }

        public new void DelListener(string type, FrameworkAction func)
        {
            this.m_Event.DelListener(type, func);
        }

        public new void DelListener<A>(string type, FrameworkAction<A> func)
        {
            this.m_Event.DelListener<A>(type, func);
        }

        public new void DelListener<A, B>(string type, FrameworkAction<A, B> func)
        {
            this.m_Event.DelListener<A, B>(type, func);
        }

        public new void DelListener<A, B, C>(string type, FrameworkAction<A, B, C> func)
        {
            this.m_Event.DelListener<A, B, C>(type, func);
        }

        public new void BroadCast(string type)
        {
            this.m_Event.BroadCast(type);
            List<IEvent> iEvents;
            if (!this.m_Type2Event.TryGetValue(type, out iEvents))
            {
                return;
            }
            foreach (IEvent iEvent in iEvents)
            {
                try
                {
                    iEvent?.Handle();
                }
                catch (Exception e)
                {
                    Log.Error(e);
                }
            }
        }

        public new void BroadCast<A>(string type, A a)
        {
            this.m_Event.BroadCast(type, a);
            List<IEvent> iEvents;
            if (!this.m_Type2Event.TryGetValue(type, out iEvents))
            {
                return;
            }
            foreach (IEvent iEvent in iEvents)
            {
                try
                {
                    iEvent?.Handle(a);
                }
                catch (Exception e)
                {
                    Log.Error(e);
                }
            }
        }

        public new void BroadCast<A, B>(string type, A a, B b)
        {
            this.m_Event.BroadCast(type, a, b);
            List<IEvent> iEvents;
            if (!this.m_Type2Event.TryGetValue(type, out iEvents))
            {
                return;
            }
            foreach (IEvent iEvent in iEvents)
            {
                try
                {
                    iEvent?.Handle(a, b);
                }
                catch (Exception e)
                {
                    Log.Error(e);
                }
            }
        }

        public new void BroadCast<A, B, C>(string type, A a, B b, C c)
        {
            this.m_Event.BroadCast(type, a, b, c);
            List<IEvent> iEvents;
            if (!this.m_Type2Event.TryGetValue(type, out iEvents))
            {
                return;
            }
            foreach (IEvent iEvent in iEvents)
            {
                try
                {
                    iEvent?.Handle(a, b, c);
                }
                catch (Exception e)
                {
                    Log.Error(e);
                }
            }
        }
        
    }
}